home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / sun4.md / devMouse.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  19KB  |  727 lines

  1. /* 
  2.  * devMouse.c --
  3.  *
  4.  *    This file implements the "mouse" device, which is used by
  5.  *    window systems to find out about keyboard and mouse events.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/sun4.md/devMouse.c,v 9.10 91/10/18 01:21:45 dlong Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include <sprite.h>
  22. #include <dev.h>
  23. #include <devAddrs.h>
  24. #include <dev/mouse.h>
  25. #include <errno.h>
  26. #include <mouse.h>
  27. #include <fs.h>
  28. #include <fsio.h>
  29. #include <list.h>
  30. #include <status.h>
  31. #include <stdlib.h>
  32. #include <timer.h>
  33. #include <tty.h>
  34. #include <ttyAttach.h>
  35. #include <z8530.h>
  36. #include <console.h>
  37. #include <user/bstring.h>
  38. #include <fsioDevice.h>
  39. /*
  40.  * For synchronization, use devTty's monitor lock (this module is
  41.  * so closely intertwined with devTty.c that this is the only logical
  42.  * approach).
  43.  */
  44.  
  45. #define LOCKPTR (&devTtyLock)
  46.  
  47. /*
  48.  * One of the structures below is dynamically allocated for each
  49.  * input event.
  50.  */
  51.  
  52. typedef struct {
  53.     List_Links links;        /* Pointers to next & previous items. */
  54.     Mouse_Event event;        /* Event. */
  55. } Event;
  56.  
  57. static List_Links eventList;    /* List of pending input events. */
  58. static int listCount;        /* Number of elements in list. */
  59. #define MAX_LIST_LENGTH 500
  60.  
  61. /*
  62.  * Other information about mouse device.  This file is strongly
  63.  * entwined with devTty.c in that this file only uses SOME of the
  64.  * devTty features (namely the ability to buffer input characters
  65.  * and process them at background level).  The output portion of
  66.  * the mouse channel is not used:  output on the mouse device goes
  67.  * to the keyboard channel.
  68.  */
  69.  
  70. static DevTty mouseTty;            /* Information used by devTty.c. */
  71. static DevZ8530 mouse = {        /* Information used by device driver. */
  72.     "mouse",                /* name */
  73. #ifdef sun4c
  74.     (DevZ8530Device *) NIL,        /* address */
  75. #else
  76.     (DevZ8530Device *) DEV_MOUSE_ADDR,    /* address */
  77. #endif
  78.     &mouseTty,                /* ttyPtr */
  79. #ifdef sun4c
  80.     0,                    /* vector */
  81. #else
  82.     DEV_UART_VECTOR,            /* vector */
  83. #endif
  84.     1200,                /* baud */
  85.     WRITE3_RX_8BIT,            /* wr3 */
  86.     WRITE5_TX_8BIT,            /* wr5 */
  87.     DevTtyInputChar,            /* inputProc */
  88.     (ClientData) &mouseTty,        /* inputData */
  89.     DevTtyOutputChar,            /* outputProc */
  90.     (ClientData) &mouseTty,        /* outputData */
  91.     0,                    /* oldRr0 */
  92.     Z_CHANNEL_B | Z_INACTIVE        /* flags */
  93. };
  94.  
  95. static Fs_NotifyToken token;        /* Used for Fs call-backs to wake up
  96.                      * waiting processes. */
  97. static volatile int outputBuffer = -1;    /* One-character output buffer shared
  98.                      * without explicit synchronization
  99.                      * between background and interrupt-
  100.                      * level procedures.  -1 means buffer
  101.                      * empty;  otherwise it contains a
  102.                      * single character to be output. */
  103. static DevZ8530 *keyboardPtr;        /* Information about the keyboard's
  104.                      * UART (needed to start up output). */
  105.  
  106. /*
  107.  * Forward declarations to procedures declared later in this file:
  108.  */
  109.  
  110. static void MouseDelayedClose _ARGS_((ClientData clientData,
  111.                                      Proc_CallInfo *callInfoPtr));
  112. static void MouseInputProc _ARGS_((ClientData dummy, int value));
  113. static void KbdInputProc _ARGS_((ClientData dummy, int value));
  114. static int MouseOutputProc _ARGS_((void));
  115.  
  116.  
  117. /*
  118.  *----------------------------------------------------------------------
  119.  *
  120.  * DevMouseInit --
  121.  *
  122.  *    Called during bootstrapping to initialize mouse-related
  123.  *    things.
  124.  *
  125.  * Results:
  126.  *    None.
  127.  *
  128.  * Side effects:
  129.  *    Resets the serial device.
  130.  *
  131.  *----------------------------------------------------------------------
  132.  */
  133.  
  134. void
  135. #ifdef sun4c
  136. DevMouseInit(virtAddr, vector)
  137.     DevZ8530Device *virtAddr;
  138.     int vector;
  139. #else
  140. DevMouseInit()
  141. #endif
  142. {
  143. #ifdef sun4c
  144.     mouse.address = virtAddr;
  145.     mouse.vector = vector;
  146. #endif
  147.     DevZ8530RawProc((Address)&mouse, TD_RAW_SHUTDOWN, 0, (char *) NULL,
  148.         0, (char *) NULL);
  149. }
  150.  
  151. /*
  152.  *----------------------------------------------------------------------
  153.  *
  154.  * DevMouseOpen --
  155.  *
  156.  *    Called through devFsOpTable to open the mouse device.
  157.  *    Initializes the device and activates it so that it's ready
  158.  *    to return input.
  159.  *
  160.  * Results:
  161.  *    A standard Sprite ReturnStatus.
  162.  *
  163.  * Side effects:
  164.  *    The mouse-related devices will be "turned on" if they aren't
  165.  *    already, which may involve setting up interrupt handlers.
  166.  *
  167.  *----------------------------------------------------------------------
  168.  */
  169.  
  170. /* ARGSUSED */
  171. ENTRY ReturnStatus
  172. DevMouseOpen(devicePtr, useFlags, notifyToken, flagsPtr)
  173.     Fs_Device *devicePtr;    /* Information about device (e.g. type
  174.                  * and unit number). */
  175.     int useFlags;        /* Flags for the stream being opened:
  176.                  * OR'ed combination of FS_READ and
  177.                  * FS_WRITE. */
  178.     Fs_NotifyToken notifyToken;    /* Used for Fs call-back to notify waiting
  179.                  * processes that the terminal is ready. */
  180.     int *flagsPtr;            /* OUT: Device IO flags */
  181. {
  182.     if (devicePtr->unit != 0) {
  183.     return Compat_MapToSprite(ENXIO);
  184.     }
  185.  
  186.     LOCK_MONITOR;
  187.  
  188.     mouseTty.openCount += 1;
  189.     if (mouseTty.openCount == 1) {
  190.     token = notifyToken;
  191.     keyboardPtr = DevGrabKeyboard(KbdInputProc, (ClientData) 0,
  192.         MouseOutputProc, (ClientData) 0);
  193.     mouseTty.insertOutput = 0;
  194.     mouseTty.extractOutput = 0;
  195.     mouseTty.rawProc = DevZ8530RawProc;
  196.     mouseTty.activateProc = DevZ8530Activate;
  197.     mouseTty.rawData = (ClientData) &mouse;
  198.     mouseTty.inputProc = MouseInputProc;
  199.     mouseTty.inputData = 0;
  200.     mouseTty.consoleFlags = 0;
  201.     List_Init(&eventList);
  202.     (*mouseTty.activateProc)(&mouse);
  203.     }
  204.  
  205.     UNLOCK_MONITOR;
  206.     return SUCCESS;
  207. }
  208.  
  209. /*
  210.  *----------------------------------------------------------------------
  211.  *
  212.  * DevMouseRead --
  213.  *
  214.  *    Called through devFsOpTable to read from the mouse device.
  215.  *
  216.  * Results:
  217.  *    A standard Sprite ReturnStatus.  Characters are stored at
  218.  *    *readPtr->buffer, and the fields of *replyPtr are modified
  219.  *    to describe what happened.  The mouse must be read in even
  220.  *    multiples of the size of Mouse_Event.
  221.  *
  222.  * Side effects:
  223.  *    Information may be removed from the mouse input queue.
  224.  *
  225.  *----------------------------------------------------------------------
  226.  */
  227.  
  228. /* ARGSUSED */
  229. ENTRY ReturnStatus
  230. DevMouseRead(devicePtr, readPtr, replyPtr)
  231.     Fs_Device *devicePtr;    /* Information about device. */
  232.     register Fs_IOParam *readPtr;    /* Input parameters. */
  233.     register Fs_IOReply *replyPtr;    /* Place to store return information. */
  234. {
  235.     int stillToDo;
  236.     char *bufPtr;
  237.  
  238.     replyPtr->length = 0;
  239.     stillToDo = readPtr->length;
  240.     bufPtr = (char *) readPtr->buffer;
  241.  
  242.     /*
  243.      * Make sure the buffer is large enough to hold at least one
  244.      * event.
  245.      */
  246.  
  247.     if (stillToDo < sizeof(Mouse_Event)) {
  248.     return Compat_MapToSprite(EINVAL);
  249.     }
  250.  
  251.     LOCK_MONITOR;
  252.  
  253.  
  254.     if (List_IsEmpty(&eventList)) {
  255.     UNLOCK_MONITOR;
  256.     return Compat_MapToSprite(EWOULDBLOCK);
  257.     }
  258.     while ((stillToDo >= sizeof(Mouse_Event)) && !List_IsEmpty(&eventList)) {
  259.     register Event *eventPtr;
  260.  
  261.     eventPtr = (Event *) List_First(&eventList);
  262.     List_Remove(&eventPtr->links);
  263.     bcopy((char *) &eventPtr->event, (char *) bufPtr, sizeof(Mouse_Event));
  264.     bufPtr += sizeof(Mouse_Event);
  265.     stillToDo -= sizeof(Mouse_Event);
  266.     replyPtr->length += sizeof(Mouse_Event);
  267.     free((char *) eventPtr);
  268.     listCount -= 1;
  269.     }
  270.     UNLOCK_MONITOR;
  271.     return SUCCESS;
  272. }
  273.  
  274. /*
  275.  *----------------------------------------------------------------------
  276.  *
  277.  * DevMouseWrite --
  278.  *
  279.  *    Called through devFsOpTable to write to the mouse device.
  280.  *
  281.  * Results:
  282.  *    A standard Sprite ReturnStatus.  Fields of *replyPtr are
  283.  *    modified to indicate what happened in the write operation.
  284.  *
  285.  * Side effects:
  286.  *    Information may be added to the output buffer for the keyboard.
  287.  *
  288.  *----------------------------------------------------------------------
  289.  */
  290.  
  291. /* ARGSUSED */
  292. ReturnStatus
  293. DevMouseWrite(devicePtr, writePtr, replyPtr)
  294.     Fs_Device *devicePtr;        /* Information about device. */
  295.     register Fs_IOParam *writePtr;    /* Input parameters. */
  296.     register Fs_IOReply *replyPtr;    /* Place to store result info. */
  297. {
  298.     ReturnStatus status = SUCCESS;
  299.     int stillToDo;
  300.     char *bufPtr;
  301.  
  302.     LOCK_MONITOR;
  303.  
  304.     replyPtr->length = 0;
  305.     stillToDo = writePtr->length;
  306.     bufPtr = (char *) writePtr->buffer;
  307.     while (stillToDo != 0) {
  308.     if (outputBuffer != -1) {
  309.         status = FS_WOULD_BLOCK;
  310.         break;
  311.     }
  312.     outputBuffer = (*((char *) bufPtr)) & 0xff;
  313.     bufPtr++;
  314.     stillToDo--;
  315.     replyPtr->length++;
  316.     DevZ8530RawProc(keyboardPtr, TD_RAW_OUTPUT_READY, 0, (char *) NIL,
  317.         0, (char *) NIL);
  318.     }
  319.     UNLOCK_MONITOR;
  320.     return status;
  321. }
  322.  
  323. /*
  324.  *----------------------------------------------------------------------
  325.  *
  326.  * DevMouseIOControl --
  327.  *
  328.  *    Called through devFsOpTable to perform IOControl operations on
  329.  *    the mouse device.
  330.  *
  331.  * Results:
  332.  *    A standard Sprite ReturnStatus.
  333.  *
  334.  * Side effects:
  335.  *    None.
  336.  *
  337.  *----------------------------------------------------------------------
  338.  */
  339.  
  340. /* ARGSUSED */
  341. ReturnStatus
  342. DevMouseIOControl(devicePtr, iocPtr, replyPtr)
  343.     Fs_Device *devicePtr;        /* Information about device. */
  344.     Fs_IOCParam *iocPtr;        /* Parameter information (buffer sizes
  345.                      * etc.). */
  346.     Fs_IOReply *replyPtr;        /* Place to store result information. */
  347. {
  348.     return Compat_MapToSprite(ENOTTY);
  349. }
  350.  
  351. /*
  352.  *----------------------------------------------------------------------
  353.  *
  354.  * DevMouseSelect --
  355.  *
  356.  *    Called through devFsOpTable to perform select-related functions
  357.  *    on the mouse device.
  358.  *
  359.  * Results:
  360.  *    Always SUCCESS.  The values at *readPtr, *writePtr, and *exceptPtr
  361.  *    get set to zero if the device is NOT readable, or writable, or
  362.  *    exception-pending, respectively.
  363.  *
  364.  * Side effects:
  365.  *    None.
  366.  *
  367.  *----------------------------------------------------------------------
  368.  */
  369.  
  370. /* ARGSUSED */
  371. ENTRY ReturnStatus
  372. DevMouseSelect(devicePtr, readPtr, writePtr, exceptPtr)
  373.     Fs_Device *devicePtr;    /* Information about device. */
  374.     int *readPtr;        /* Set to zero if device not readable. */
  375.     int *writePtr;        /* Set to zero if device not writable. */
  376.     int *exceptPtr;        /* Set to zero if no exception pending on
  377.                  * device. */
  378. {
  379.     LOCK_MONITOR;
  380.     if (List_IsEmpty(&eventList)) {
  381.     *readPtr = 0;
  382.     }
  383.     if (outputBuffer != -1) {
  384.     *writePtr = 0;
  385.     }
  386.     *exceptPtr = 0;
  387.     UNLOCK_MONITOR;
  388.     return SUCCESS;
  389. }
  390.  
  391. /*
  392.  *----------------------------------------------------------------------
  393.  *
  394.  * DevMouseClose --
  395.  *
  396.  *    Called through devFsOpTable when the mouse device is closed.
  397.  *
  398.  * Results:
  399.  *    A standard Sprite return status.
  400.  *
  401.  * Side effects:
  402.  *    Data structures get cleaned up and possibly deallocated.
  403.  *
  404.  *----------------------------------------------------------------------
  405.  */
  406.  
  407. /* ARGSUSED */
  408. ReturnStatus
  409. DevMouseClose(devicePtr, useFlags, openCount, writerCount)
  410.     Fs_Device *devicePtr;        /* Information about device. */
  411.     int useFlags;            /* Indicates whether stream being
  412.                      * closed was open for reading and/or
  413.                      * writing:  OR'ed combination of
  414.                      * FS_READ and FS_WRITE. */
  415.     int openCount;            /* # of opens still active for this
  416.                      * device. */
  417.     int writerCount;            /* # of active opens that permit
  418.                      * writing. */
  419. {
  420.     LOCK_MONITOR;
  421.     mouseTty.openCount -= 1;
  422.     if (mouseTty.openCount == 0) {
  423.     while (!List_IsEmpty(&eventList)) {
  424.         List_Links *eventPtr;
  425.     
  426.         eventPtr = List_First(&eventList);
  427.         List_Remove(eventPtr);
  428.         free((char *) eventPtr);
  429.     }
  430.     
  431.     /*
  432.      * If I/O is still in progress, delay shutting down the device
  433.      * until the I/O completes.
  434.      */
  435.     
  436.     if (outputBuffer == -1) {
  437.         DevReleaseKeyboard();
  438.         (void) (*mouseTty.rawProc)(mouseTty.rawData, TD_RAW_SHUTDOWN, 0,
  439.             (char *) NULL, 0, (char *) NULL);
  440.     }
  441.     }
  442.     UNLOCK_MONITOR;
  443.     return SUCCESS;
  444. }
  445.  
  446. /*
  447.  *----------------------------------------------------------------------
  448.  *
  449.  * MouseDelayedClose --
  450.  *
  451.  *    Background-level procedure to complete the device close if
  452.  *    it couldn't be completed at close-time because I/O was still
  453.  *    in progress.
  454.  *
  455.  * Results:
  456.  *    None.
  457.  *
  458.  * Side effects:
  459.  *    The mouse gets shutdown and the keyboard reverts to normal
  460.  *    operation.
  461.  *
  462.  *----------------------------------------------------------------------
  463.  */
  464. /*ARGSUSED*/
  465. static void
  466. MouseDelayedClose(clientData, callInfoPtr)
  467.     ClientData     clientData;        /* Not used. */
  468.     Proc_CallInfo *callInfoPtr;         /* Not used. */
  469. {
  470.     LOCK_MONITOR;
  471.     if (mouseTty.openCount == 0) {
  472.     DevReleaseKeyboard();
  473.     (void) (*mouseTty.rawProc)(mouseTty.rawData, TD_RAW_SHUTDOWN, 0,
  474.         (char *) NULL, 0, (char *) NULL);
  475.     }
  476.     UNLOCK_MONITOR;
  477. }
  478.  
  479. /*
  480.  *----------------------------------------------------------------------
  481.  *
  482.  * DevMouseInterrupt --
  483.  *
  484.  *    This procedure is invoked whenever an interrupt occurs
  485.  *    for one of the Z8530 chips.
  486.  *
  487.  * Results:
  488.  *    None.
  489.  *
  490.  * Side effects:
  491.  *    The Z8530 interrupt handler gets invoked to see if anything
  492.  *    happened related to the mouse UART.
  493.  *
  494.  *----------------------------------------------------------------------
  495.  */
  496.  
  497. void
  498. DevMouseInterrupt()
  499. {
  500.     DevZ8530Interrupt((ClientData)&mouse);
  501. }
  502.  
  503. /*
  504.  *----------------------------------------------------------------------
  505.  *
  506.  * MouseInputProc --
  507.  *
  508.  *    This procedure is invoked at background level (i.e in a kernel
  509.  *    process) to handle input characters from the mouse UART.  The
  510.  *    caller is expected to have acquired the tty monitor lock.
  511.  *
  512.  * Results:
  513.  *    None.
  514.  *
  515.  * Side effects:
  516.  *    The input character is converted to an event, which is then
  517.  *    enqueued on an input queue.
  518.  *
  519.  *----------------------------------------------------------------------
  520.  */
  521.  
  522. /* ARGSUSED */
  523. INTERNAL static void
  524. MouseInputProc(dummy, value)
  525.     ClientData dummy;        /* Not used. */
  526.     int value;            /* Character that arrived from UART. */
  527. {
  528.     char c;
  529.     Time time;
  530.     Event *eventPtr;
  531.  
  532.     /*
  533.      * Mouse characters arrive in bunches, with the first character
  534.      * of each bunch specially marked.  A simple state machine here
  535.      * keeps track of where we are in the bunch.
  536.      */
  537.  
  538. #define WAIT_SYNC    0
  539. #define WAIT_DELTA_X1    1
  540. #define WAIT_DELTA_Y1    2
  541. #define WAIT_DELTA_X2    3
  542. #define WAIT_DELTA_Y2    4
  543.  
  544. #define NUM_STATES    5
  545. #define SYNC_BIT     0x80
  546.  
  547.     static int curState = WAIT_SYNC;
  548.     static Mouse_Event event;
  549.  
  550.     /*
  551.      * Discard any special characters (breaks, etc.).
  552.      */
  553.  
  554.     if (DEV_TTY_IS_CONTROL(value)) {
  555.     return;
  556.     }
  557.     c = value;
  558.  
  559.     /*
  560.      * The check below keeps our state machine back in sync with the
  561.      * mouse by discarding characters up to the beginning of the next
  562.      * sequence.
  563.      */
  564.  
  565.     if ((curState == WAIT_SYNC) && !(c & SYNC_BIT)) {
  566.     return;
  567.     }
  568.     switch (curState) {
  569.     case WAIT_SYNC:
  570.         event.key = c & 0x7;
  571.         break;
  572.     case WAIT_DELTA_X1:
  573.         event.deltaX = (int) c;
  574.         break;
  575.     case WAIT_DELTA_Y1:
  576.         event.deltaY = (int) c;
  577.         break;
  578.     case WAIT_DELTA_X2:
  579.         event.deltaX += (int) c;
  580.         break;
  581.     case WAIT_DELTA_Y2:
  582.         event.deltaY += (int) c;
  583.         event.flags = MOUSE_EVENT;
  584.         Timer_GetRealTimeOfDay(&time, (int *) NIL, (Boolean *) NIL);
  585.         event.time = (time.seconds*1000) + (time.microseconds/1000);
  586.         eventPtr = (Event *) malloc(sizeof(Event));
  587.         List_InitElement(&eventPtr->links);
  588.         eventPtr->event = event;
  589.         List_Insert(&eventPtr->links, LIST_ATREAR(&eventList));
  590.         dev_LastConsoleInput = time;
  591.         Fsio_DevNotifyReader(token);
  592.         break;
  593.     }
  594.     curState++;
  595.     if (curState >= NUM_STATES) {
  596.     curState = 0;
  597.     }
  598. }
  599.  
  600. /*
  601.  *----------------------------------------------------------------------
  602.  *
  603.  * KbdInputProc --
  604.  *
  605.  *    This procedure is invoked at background level (i.e in a kernel
  606.  *    process) to handle input characters from the keyboard UART.
  607.  *    This procedure is invoked only when the mouse device is open.
  608.  *    The caller is expected to have acquired the tty monitor lock.
  609.  *
  610.  * Results:
  611.  *    None.
  612.  *
  613.  * Side effects:
  614.  *    The input character is converted to an event, which is then
  615.  *    enqueued on an input queue.
  616.  *
  617.  *----------------------------------------------------------------------
  618.  */
  619.  
  620. /* ARGSUSED */
  621. INTERNAL static void
  622. KbdInputProc(dummy, value)
  623.     ClientData dummy;        /* Not used. */
  624.     int value;            /* Character that arrived from UART:
  625.                  * identifies which key, and whether up
  626.                  * or down transition. */
  627. {
  628.     register Event *eventPtr;
  629.     Time time;
  630.  
  631.     /*
  632.      * Throw away control events and anything corresponding to a console
  633.      * command.
  634.      */
  635.  
  636.     if (DEV_TTY_IS_CONTROL(value)) {
  637.     return;
  638.     }
  639.     if (DevConsoleConvertKeystroke(value) == -2) {
  640.     return;
  641.     }
  642.  
  643.     eventPtr = (Event *) malloc(sizeof(Event));
  644.     List_InitElement(&eventPtr->links);
  645.     eventPtr->event.flags = KEYBOARD_EVENT;
  646.     if (value & 0x80) {
  647.     eventPtr->event.flags |= KEY_UP;
  648.     }
  649.     eventPtr->event.key = value & 0x7f;
  650.     eventPtr->event.deltaX = 0;
  651.     eventPtr->event.deltaY = 0;
  652.     Timer_GetRealTimeOfDay(&time, (int *) NIL, (Boolean *) NIL);
  653.     eventPtr->event.time = (time.seconds*1000) + (time.microseconds/1000);
  654.     List_Insert(&eventPtr->links, LIST_ATREAR(&eventList));
  655.     dev_LastConsoleInput = time;
  656.     Fsio_DevNotifyReader(token);
  657. }
  658.  
  659. /*
  660.  *----------------------------------------------------------------------
  661.  *
  662.  * MouseOutputProc --
  663.  *
  664.  *    This procedure is called at interrupt level to fetch the
  665.  *    next output character for the mouse device (these output
  666.  *    characters go to the keyboard).
  667.  *
  668.  * Results:
  669.  *    Returns the next output character, or -1 if the output buffer
  670.  *    is empty.
  671.  *
  672.  * Side effects:
  673.  *    May wake up processes waiting to write to this device because
  674.  *    the output buffer was full.
  675.  *
  676.  *----------------------------------------------------------------------
  677.  */
  678.  
  679. static int
  680. MouseOutputProc()
  681. {
  682.     int result;
  683.  
  684.     result = outputBuffer;
  685.     if (result != -1) {
  686.     outputBuffer = -1;
  687.     if (mouseTty.openCount > 0) {
  688.         Fsio_DevNotifyWriter(token);
  689.     } else {
  690.         Proc_CallFunc(MouseDelayedClose, (ClientData) NIL, 0);
  691.     }
  692.     }
  693.     return result;
  694. }
  695.  
  696. /*
  697.  *----------------------------------------------------------------------
  698.  *
  699.  * Dev_ConsoleReset --
  700.  *
  701.  *    This procedure is called as a console command procedure to
  702.  *    switch console keyboard input back and forth between /dev/mouse
  703.  *    and /dev/console.
  704.  *
  705.  * Results:
  706.  *    None.
  707.  *
  708.  * Side effects:
  709.  *    None.
  710.  *
  711.  *----------------------------------------------------------------------
  712.  */
  713.  
  714. void
  715. Dev_ConsoleReset(toConsole)
  716.     int toConsole;            /* 1 means make keystrokes go to
  717.                      * console.  0 means make keystrokes
  718.                      * go to mouse device. */
  719. {
  720.     if (toConsole) {
  721.     DevReleaseKeyboard();
  722.     } else {
  723.     keyboardPtr = DevGrabKeyboard(KbdInputProc, (ClientData) 0,
  724.         MouseOutputProc, (ClientData) 0);
  725.     }
  726. }
  727.